from lib.database import DBConnections
import manageTorrents
from lib import Model
import feedparser
import re
from datetime import datetime, timedelta
import urllib
from lib.list_search import Operators, Clause
import shutil, os, sys

from supay import Daemon

#get the databases arena object
dbConnections = DBConnections()

#get the database of the application
dbSession = dbConnections.getConnection('app')

def checkEpisodes(transmission):    
    def downloadTorrent(url):
        (tmpFile, info) = urllib.urlretrieve(url, 'tmp/' + datetime.now().isoformat() + '.torrent')
        return tmpFile
    
    #begin transaction
    dbSession.begin()
    
    try:
        #default feed
        feedUrl = "http://rss.bt-chat.com/?group=3&cat=9"
        feedContents = feedparser.parse(feedUrl)
        
        #get the active seasons
        seasons = dbSession.query(Model.Season).filter('active = 1')
        
        #for each season check the feed
        feedData = dict()
        for season in seasons:
            #get the episodes already downloaded
            episodes = season.episodes
            
            #check for new episodes in the feed
            feed = feedContents
            for item in feed.entries:
                #check if the item belongs to the serie and season
                patterns = ("%s(\s+|\.)(S%sE\d+)" % (season.serie.name, season.name), 
                            "(\.XviD)|(HDTV-)|(.XviD)")
                validItem = True
                for pattern in patterns:
                    if (not re.search(pattern, item.title, re.IGNORECASE)):
                        validItem = False
                        break #stop the loop
                
                if (validItem):
                    patterns = ('S\d+E(\d+)', '\.\d+x(\d+)\.')
                    for pattern in patterns:
                        epNumber = re.search(pattern, item.title)
                        if (epNumber):
                            epNumber = epNumber.group(1)
                            break #stop loop, episode number getted
                    
                    #check if we don't have the episode
                    lstEpisodes = map(lambda ep: ep.name, episodes)
                    if (epNumber and (not epNumber in lstEpisodes)): #if is valid epNumber (!= None), and doesn't exists yet
                        link = None
                        if (item.has_key('links')):
                           link = item.links[0]['href']
                        else:
                           link = item.link

                        #download the torrent file
                        torrentFile = downloadTorrent(link)
                         
                        #sent the torrent to download
                        torrent = transmission.add(torrentFile)
                         
                        #create the episode object
                        torrent_obj = torrent[torrent.keys()[0]]
                        episode = Model.Episode(epNumber, torrent_obj.name, 'D', torrent_obj.id)
                        episode.season = season
                        
                        #set the episode on list of downloaded
                        episodes.append(episode)
                        
                        #add episode to database
                        dbSession.add(episode)
                        
        dbSession.commit()
    except Exception, (ex):
        dbSession.rollback()
        raise ex
    #finally:
    #    pass

#check for episodes already downloaded
def checkDownloaded(transmission):
    def _move_files(episode):
        #move files
        srcDir = transmission.getConfig('download_dir')
        destDir = '/media/disk/Videos/'
        
        #episode destination
        destination = (episode.season.serie.name, episode.season.name)
        for dest in destination:
            #check if path exists, if not create it
            destDir += '/' + dest
            if (not os.path.exists(destDir)):
                os.mkdir(destDir)
        
        #move file to destination
        shutil.move(srcDir + '/' + episode.description,
                    '%s/%s' % (destDir, episode.description))
        
        
    #begin transaction
    dbSession.begin()
        
    try:
        #get torrent downloading
        episodes = dbSession.query(Model.Episode).filter("status = 'D'")
        for ep in episodes:
            setToSubtitles = True #change episode status to 'S'
                
            #get the torrent on transmission
            torrent = transmission.search([Clause('id', Operators.Equal(re.I), value=ep.torrent_id)])
            if (len(torrent) > 0): #if the torrent exist
                torrent = torrent[0]
                    
                if (round(torrent.progress, 0) == 100): #if 100%, fully downloaded
                    #remove from the transmission
                    transmission.remove(torrent.id)
                else: 
                    #not fully downloaded, don't send to subtitles
                    setToSubtitles = False
                
            if (setToSubtitles):
                #set the episode to get the subtitle
                ep.status = 'S'
                    
                #set the torrent_id to Null
                ep.torrent_id = None
                    
                #move file to proper directory
                _move_files(ep)
        
        dbSession.commit()
    #finally:
        #pass
    except Exception, (ex):
        dbSession.rollback()
        raise ex

#check for subtitles to the newly downloaded torrents
def checkSubtitles(transmission): 
    #get the episodes that need subtitle (opensubtitles)
    epSubtitles = dbSession.query(Model.Episode).filter("status = 'S'")
    for ep in epSubtitles:
        pass
    

#calculate the next time to run
def _calc_next_run(curDateTime, interval):
    diff = timedelta(minutes=interval)
    
    return curDateTime + diff
    

#daemon process
def run(daemon):
    if (daemon != None):
        daemon.start()
    
    #transmission client
    transmission = manageTorrents.ManageTorrents('localhost', 9091)
    
    #timers
    timers = [{'name': 'episodes', 'interval'  : 60, 'run': None},
              {'name': 'downloaded', 'interval': 60, 'run': None},
              {'name': 'subtitles', 'interval' : 65, 'run': None}
             ]
    processing = None

    while (True):
        try: 
            #get the current time
            curDateTime = datetime.now()
            
            for process in timers:
                if (process['run'] == None or curDateTime >= process['run']):
                    processing = process
                    
                    print("checking for new %s... - %s" % (process['name'], str(curDateTime)))
                    
                    #execute the method
                    method = eval("check" + process['name'].capitalize())
                    method(transmission)
                    ###
           
                    #set the next time to run
                    process['run'] = _calc_next_run(curDateTime, process['interval'])
           
                    print('DONE, waiting for next run...')
        except Exception, (ex):
            print("Error START: %s" % (datetime.now().isoformat()))
            print(ex)
            print("Error END %s" % (datetime.now().isoformat()))
            
            #set the next time to run
            processing['run'] = _calc_next_run(curDateTime, processing['interval'])
            print('DONE, waiting for next run...')
            

if __name__ == "__main__":
    try:
        if (len(sys.argv) == 2):
            sys.argv[1] = sys.argv[1].lower()
            
            if (sys.argv[1] == 'no-daemon'):
                run(None)
            else: #run has a daemon
                #get current directory
                currentDir = os.path.abspath(os.path.dirname(__file__))
                
                #create daemon object
                daemon = Daemon(name='torrent-daemon', pid_dir=currentDir + '/tmp', stdout=currentDir + '/tmp/logs')
                
                if ('start' == sys.argv[1]):
                    run(daemon)
                elif ('stop' == sys.argv[1]):
                    daemon.stop()
                elif ('restart' == sys.argv[1]):
                    daemon.stop()
                    run(daemon)
                else:
                    raise Exception("Unknown command")
        else:
            raise Exception("usage: %s start|stop|restart|no-daemon" % sys.argv[0])
    except Exception, (ex):
        print(ex)
    finally:
        dbSession.close()
